package com.lifeverse.service;

import com.lifeverse.entity.Decision;
import com.lifeverse.entity.DecisionHistory;
import com.lifeverse.entity.LifeEntity;
import com.lifeverse.entity.Rule;
import com.lifeverse.entity.enums.DecisionStatus;
import com.lifeverse.entity.enums.DecisionType;
import com.lifeverse.repository.DecisionHistoryRepository;
import com.lifeverse.repository.DecisionRepository;
import com.lifeverse.util.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 决策引擎核心服务
 * 负责处理生命体的决策制定和执行
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DecisionEngine {
    
    private final DecisionRepository decisionRepository;
    private final DecisionHistoryRepository decisionHistoryRepository;
    private final RuleEngine ruleEngine;
    private final DecisionEvaluator decisionEvaluator;
    private final DecisionExecutor decisionExecutor;
    
    /**
     * 创建决策
     */
    @Transactional
    public Decision createDecision(LifeEntity lifeEntity, DecisionType type, String title, 
                                 String description, Map<String, Object> context) {
        log.info("创建决策 - 生命体: {}, 类型: {}, 标题: {}", lifeEntity.getName(), type, title);
        
        Decision decision = new Decision();
        decision.setLifeEntity(lifeEntity);
        decision.setType(type);
        decision.setTitle(title);
        decision.setDescription(description);
        decision.setContext(JsonUtils.toJson(context));
        decision.setStatus(DecisionStatus.PENDING);
        
        // 设置超时时间（默认1小时）
        decision.setTimeoutAt(LocalDateTime.now().plusHours(1));
        
        Decision savedDecision = decisionRepository.save(decision);
        
        // 记录历史
        recordHistory(savedDecision, "CREATE", "决策创建", null, 
                     DecisionStatus.PENDING.name(), "SYSTEM");
        
        log.info("决策创建成功 - ID: {}", savedDecision.getId());
        return savedDecision;
    }
    
    /**
     * 处理决策
     */
    @Transactional
    public CompletableFuture<Decision> processDecision(Long decisionId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Decision decision = decisionRepository.findById(decisionId)
                    .orElseThrow(() -> new RuntimeException("决策不存在: " + decisionId));
                
                log.info("开始处理决策 - ID: {}, 标题: {}", decisionId, decision.getTitle());
                
                // 更新状态为分析中
                updateDecisionStatus(decision, DecisionStatus.ANALYZING, "开始分析决策");
                
                // 分析决策上下文
                DecisionContext context = analyzeContext(decision);
                
                // 生成决策选项
                List<DecisionOption> options = generateOptions(decision, context);
                decision.setOptions(JsonUtils.toJson(options));
                
                // 更新状态为评估中
                updateDecisionStatus(decision, DecisionStatus.EVALUATING, "开始评估决策选项");
                
                // 评估决策选项
                DecisionEvaluation evaluation = decisionEvaluator.evaluate(decision, options, context);
                
                // 选择最佳选项
                DecisionOption bestOption = selectBestOption(options, evaluation);
                
                // 完成决策
                decision.complete(JsonUtils.toJson(bestOption), evaluation.getReasoning(), 
                                evaluation.getConfidence());
                
                Decision savedDecision = decisionRepository.save(decision);
                
                recordHistory(savedDecision, "COMPLETE", "决策完成", 
                            DecisionStatus.EVALUATING.name(), DecisionStatus.DECIDED.name(), "SYSTEM");
                
                log.info("决策处理完成 - ID: {}, 选择方案: {}", decisionId, bestOption.getName());
                return savedDecision;
                
            } catch (Exception e) {
                log.error("决策处理失败 - ID: {}", decisionId, e);
                handleDecisionError(decisionId, e);
                throw new RuntimeException("决策处理失败", e);
            }
        });
    }
    
    /**
     * 执行决策
     */
    @Transactional
    public CompletableFuture<Decision> executeDecision(Long decisionId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Decision decision = decisionRepository.findById(decisionId)
                    .orElseThrow(() -> new RuntimeException("决策不存在: " + decisionId));
                
                if (!decision.getStatus().canExecute()) {
                    throw new RuntimeException("决策状态不允许执行: " + decision.getStatus());
                }
                
                log.info("开始执行决策 - ID: {}, 标题: {}", decisionId, decision.getTitle());
                
                // 更新状态为执行中
                decision.execute();
                Decision savedDecision = decisionRepository.save(decision);
                
                recordHistory(savedDecision, "EXECUTE", "开始执行决策", 
                            DecisionStatus.DECIDED.name(), DecisionStatus.EXECUTING.name(), "SYSTEM");
                
                // 执行决策
                DecisionExecutionResult result = decisionExecutor.execute(savedDecision);
                
                // 更新执行结果
                if (result.isSuccess()) {
                    savedDecision.markCompleted(result.getActualImpact());
                    recordHistory(savedDecision, "SUCCESS", "决策执行成功", 
                                DecisionStatus.EXECUTING.name(), DecisionStatus.COMPLETED.name(), "SYSTEM");
                } else {
                    savedDecision.markFailed(result.getErrorMessage());
                    recordHistory(savedDecision, "FAILED", "决策执行失败: " + result.getErrorMessage(), 
                                DecisionStatus.EXECUTING.name(), DecisionStatus.FAILED.name(), "SYSTEM");
                }
                
                Decision finalDecision = decisionRepository.save(savedDecision);
                
                log.info("决策执行完成 - ID: {}, 结果: {}", decisionId, 
                        result.isSuccess() ? "成功" : "失败");
                
                return finalDecision;
                
            } catch (Exception e) {
                log.error("决策执行失败 - ID: {}", decisionId, e);
                handleDecisionError(decisionId, e);
                throw new RuntimeException("决策执行失败", e);
            }
        });
    }
    
    /**
     * 分析决策上下文
     */
    private DecisionContext analyzeContext(Decision decision) {
        log.debug("分析决策上下文 - 决策ID: {}", decision.getId());
        
        DecisionContext context = new DecisionContext();
        context.setDecision(decision);
        context.setLifeEntity(decision.getLifeEntity());
        context.setEnvironment(getCurrentEnvironment(decision.getLifeEntity()));
        context.setConstraints(getDecisionConstraints(decision));
        context.setObjectives(getDecisionObjectives(decision));
        
        // 获取相关规则
        List<Rule> applicableRules = ruleEngine.getApplicableRules(decision);
        context.setApplicableRules(applicableRules);
        
        return context;
    }
    
    /**
     * 生成决策选项
     */
    private List<DecisionOption> generateOptions(Decision decision, DecisionContext context) {
        log.debug("生成决策选项 - 决策ID: {}", decision.getId());
        
        List<DecisionOption> options = new ArrayList<>();
        
        // 基于规则生成选项
        for (Rule rule : context.getApplicableRules()) {
            DecisionOption option = generateOptionFromRule(rule, context);
            if (option != null) {
                options.add(option);
            }
        }
        
        // 基于历史决策生成选项
        List<DecisionOption> historicalOptions = generateOptionsFromHistory(decision, context);
        options.addAll(historicalOptions);
        
        // 生成创新选项
        List<DecisionOption> innovativeOptions = generateInnovativeOptions(decision, context);
        options.addAll(innovativeOptions);
        
        // 确保至少有一个默认选项
        if (options.isEmpty()) {
            options.add(createDefaultOption(decision, context));
        }
        
        log.debug("生成了 {} 个决策选项", options.size());
        return options;
    }
    
    /**
     * 选择最佳选项
     */
    private DecisionOption selectBestOption(List<DecisionOption> options, DecisionEvaluation evaluation) {
        return options.stream()
                .max(Comparator.comparing(option -> evaluation.getOptionScore(option.getId())))
                .orElse(options.get(0));
    }
    
    /**
     * 更新决策状态
     */
    private void updateDecisionStatus(Decision decision, DecisionStatus newStatus, String description) {
        DecisionStatus oldStatus = decision.getStatus();
        decision.setStatus(newStatus);
        decisionRepository.save(decision);
        
        recordHistory(decision, "STATUS_CHANGE", description, 
                     oldStatus.name(), newStatus.name(), "SYSTEM");
    }
    
    /**
     * 记录决策历史
     */
    private void recordHistory(Decision decision, String actionType, String description, 
                             String previousState, String newState, String actor) {
        DecisionHistory history = DecisionHistory.create(decision, actionType, description, 
                                                        previousState, newState, actor);
        decisionHistoryRepository.save(history);
    }
    
    /**
     * 处理决策错误
     */
    private void handleDecisionError(Long decisionId, Exception e) {
        try {
            Decision decision = decisionRepository.findById(decisionId).orElse(null);
            if (decision != null) {
                decision.markFailed(e.getMessage());
                decisionRepository.save(decision);
                
                recordHistory(decision, "ERROR", "决策处理出错: " + e.getMessage(), 
                            decision.getStatus().name(), DecisionStatus.FAILED.name(), "SYSTEM");
            }
        } catch (Exception ex) {
            log.error("处理决策错误时发生异常", ex);
        }
    }
    
    /**
     * 获取当前环境信息
     */
    private Map<String, Object> getCurrentEnvironment(LifeEntity lifeEntity) {
        Map<String, Object> environment = new HashMap<>();
        environment.put("lifeEntityId", lifeEntity.getId());
        environment.put("lifeEntityType", lifeEntity.getType());
        environment.put("consciousnessLevel", lifeEntity.getConsciousnessLevel());
        environment.put("energyLevel", lifeEntity.getEnergyLevel());
        environment.put("healthScore", lifeEntity.getHealthScore());
        environment.put("timestamp", LocalDateTime.now());
        return environment;
    }
    
    /**
     * 获取决策约束
     */
    private List<String> getDecisionConstraints(Decision decision) {
        List<String> constraints = new ArrayList<>();
        
        // 基于生命体类型的约束
        switch (decision.getLifeEntity().getType()) {
            case CORPORATE:
                constraints.add("必须符合商业伦理");
                constraints.add("必须考虑利益相关者");
                break;
            case URBAN:
                constraints.add("必须考虑公共利益");
                constraints.add("必须符合城市规划");
                break;
            case INDIVIDUAL:
                constraints.add("必须尊重个人隐私");
                constraints.add("必须符合个人价值观");
                break;
            default:
                constraints.add("必须符合基本伦理原则");
        }
        
        return constraints;
    }
    
    /**
     * 获取决策目标
     */
    private List<String> getDecisionObjectives(Decision decision) {
        List<String> objectives = new ArrayList<>();
        
        // 基于决策类型的目标
        switch (decision.getType()) {
            case RESOURCE_ALLOCATION:
                objectives.add("优化资源利用效率");
                objectives.add("确保公平分配");
                break;
            case COLLABORATION:
                objectives.add("提高协作效果");
                objectives.add("增强团队凝聚力");
                break;
            case EVOLUTION:
                objectives.add("促进能力提升");
                objectives.add("保持系统稳定");
                break;
            default:
                objectives.add("实现最大化价值");
        }
        
        return objectives;
    }
    
    /**
     * 从规则生成选项
     */
    private DecisionOption generateOptionFromRule(Rule rule, DecisionContext context) {
        // 这里应该根据规则的动作部分生成具体的决策选项
        // 简化实现
        DecisionOption option = new DecisionOption();
        option.setId(UUID.randomUUID().toString());
        option.setName("基于规则: " + rule.getName());
        option.setDescription(rule.getDescription());
        option.setSource("RULE");
        option.setSourceId(rule.getId().toString());
        return option;
    }
    
    /**
     * 从历史决策生成选项
     */
    private List<DecisionOption> generateOptionsFromHistory(Decision decision, DecisionContext context) {
        // 查找类似的历史决策
        List<Decision> similarDecisions = decisionRepository.findByLifeEntityAndType(
                decision.getLifeEntity(), decision.getType());
        
        return similarDecisions.stream()
                .filter(d -> d.getStatus() == DecisionStatus.COMPLETED)
                .filter(d -> d.getActualImpact() != null && d.getActualImpact().compareTo(BigDecimal.ZERO) > 0)
                .limit(3)
                .map(this::createOptionFromHistoricalDecision)
                .collect(Collectors.toList());
    }
    
    /**
     * 生成创新选项
     */
    private List<DecisionOption> generateInnovativeOptions(Decision decision, DecisionContext context) {
        List<DecisionOption> options = new ArrayList<>();
        
        // 基于生命体的创造力分数生成创新选项
        BigDecimal creativity = decision.getLifeEntity().getCreativityScore();
        if (creativity.compareTo(BigDecimal.valueOf(50)) > 0) {
            DecisionOption innovativeOption = new DecisionOption();
            innovativeOption.setId(UUID.randomUUID().toString());
            innovativeOption.setName("创新方案");
            innovativeOption.setDescription("基于创造力生成的创新解决方案");
            innovativeOption.setSource("INNOVATION");
            options.add(innovativeOption);
        }
        
        return options;
    }
    
    /**
     * 创建默认选项
     */
    private DecisionOption createDefaultOption(Decision decision, DecisionContext context) {
        DecisionOption option = new DecisionOption();
        option.setId(UUID.randomUUID().toString());
        option.setName("默认方案");
        option.setDescription("保持现状，不做改变");
        option.setSource("DEFAULT");
        return option;
    }
    
    /**
     * 从历史决策创建选项
     */
    private DecisionOption createOptionFromHistoricalDecision(Decision historicalDecision) {
        DecisionOption option = new DecisionOption();
        option.setId(UUID.randomUUID().toString());
        option.setName("参考历史: " + historicalDecision.getTitle());
        option.setDescription("基于历史成功决策的方案");
        option.setSource("HISTORY");
        option.setSourceId(historicalDecision.getId().toString());
        return option;
    }
    
    // 内部类定义
    public static class DecisionContext {
        private Decision decision;
        private LifeEntity lifeEntity;
        private Map<String, Object> environment;
        private List<String> constraints;
        private List<String> objectives;
        private List<Rule> applicableRules;
        
        // getters and setters
        public Decision getDecision() { return decision; }
        public void setDecision(Decision decision) { this.decision = decision; }
        public LifeEntity getLifeEntity() { return lifeEntity; }
        public void setLifeEntity(LifeEntity lifeEntity) { this.lifeEntity = lifeEntity; }
        public Map<String, Object> getEnvironment() { return environment; }
        public void setEnvironment(Map<String, Object> environment) { this.environment = environment; }
        public List<String> getConstraints() { return constraints; }
        public void setConstraints(List<String> constraints) { this.constraints = constraints; }
        public List<String> getObjectives() { return objectives; }
        public void setObjectives(List<String> objectives) { this.objectives = objectives; }
        public List<Rule> getApplicableRules() { return applicableRules; }
        public void setApplicableRules(List<Rule> applicableRules) { this.applicableRules = applicableRules; }
    }
    
    public static class DecisionOption {
        private String id;
        private String name;
        private String description;
        private String source;
        private String sourceId;
        private Map<String, Object> parameters;
        
        // getters and setters
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        public String getSource() { return source; }
        public void setSource(String source) { this.source = source; }
        public String getSourceId() { return sourceId; }
        public void setSourceId(String sourceId) { this.sourceId = sourceId; }
        public Map<String, Object> getParameters() { return parameters; }
        public void setParameters(Map<String, Object> parameters) { this.parameters = parameters; }
    }
    
    public static class DecisionEvaluation {
        private String reasoning;
        private BigDecimal confidence;
        private Map<String, BigDecimal> optionScores;
        
        // getters and setters
        public String getReasoning() { return reasoning; }
        public void setReasoning(String reasoning) { this.reasoning = reasoning; }
        public BigDecimal getConfidence() { return confidence; }
        public void setConfidence(BigDecimal confidence) { this.confidence = confidence; }
        public Map<String, BigDecimal> getOptionScores() { return optionScores; }
        public void setOptionScores(Map<String, BigDecimal> optionScores) { this.optionScores = optionScores; }
        
        public BigDecimal getOptionScore(String optionId) {
            return optionScores.getOrDefault(optionId, BigDecimal.ZERO);
        }
    }
    
    public static class DecisionExecutionResult {
        private boolean success;
        private String errorMessage;
        private BigDecimal actualImpact;
        private Map<String, Object> results;
        
        // getters and setters
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        public String getErrorMessage() { return errorMessage; }
        public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
        public BigDecimal getActualImpact() { return actualImpact; }
        public void setActualImpact(BigDecimal actualImpact) { this.actualImpact = actualImpact; }
        public Map<String, Object> getResults() { return results; }
        public void setResults(Map<String, Object> results) { this.results = results; }
    }
}